package uform.ui.comp;
import uform.ui.assembler.Assembler;
import uform.model.value.ValueType;
import uform.ui.assembler.IComponentAssembler;
import thx.error.Error;
import uform.ui.comp.Container;
using Types;
import uform.model.value.StringType;
import uform.ui.comp.Component;     
import uform.model.core.Schema;
import thx.error.NullArgument;
import uform.ui.comp.Group;
import uform.model.core.Model; 

class Form extends Group
{    
	public var model(default, setModel) : Model;  
	var _component : Component;
	public var action(default, null) : Trigger;
	var _handler : Void -> Void;
	var _assembler : Assembler;         
	public var mode(default, null) : FormMode;
	
	var _submit : Bool;
	
	public function new(?name : String, ?mode : FormMode, ?model : Model)
	{
		super(name);
		_submit = false;
		this.mode = null == mode ? FormMode.Standalone : mode;
		
		switch(this.mode)
		{
			case FormMode.Standalone:
				//
			case FormMode.HttpSubmit(_, name, value, _, _, handler):
				if (null == name)
					name = "submit";
				if (null == value)
					value = "submit";
				_handler = handler;
				action = new Trigger(name, value, TriggerKind.Submit, handle);
				untyped action._parent.set(this);
		}
		
		_assembler = new Assembler(this);                                                      
		if(null == model)
			this.model = new Model();
		else                                        
			this.model = model;
	}                        
	
	public function isSubmit() return _submit
	
	function handle()
	{
		_submit = true;
		if(null != _handler)
			_handler();
	}
	
	function setModel(model : Model)
	{    
		if(this.model != null)
		{
			this.model.onSchema.remove(_onSchema);
		}
		if(null == model)
		{   
			_clearComponent();
			this.model = null;
			return null;
		}   
		
		this.model = model;
		setPrefix();
		this.model.onSchema.add(_onSchema);	
		_onSchema();
		
		return model;
	}    

	override function _id()
	{
		if (null == name || "" == name) 
			return "M";
		else
			return name;
	}
	
	function _clearComponent()
	{
		if(null != _component)
			_component.dispose();
		_component = null;
	}
	
	function _onSchema()
	{         
        _clearComponent();
		
		if (null != model.schema)
		{
			_component = _assembler.assemble(model.schema);
			this._parentFor(_component);
		}
	}
	
	override function setName(name : String)
	{
		if (name == null || name == "")
			throw new Error("invalid empty name for Form");
		super.setName(name);
		setPrefix();
		return name;
	}
	
	function setPrefix()
	{
		if (null == model)
			return;
		model.prefix = (null == name || "" == name) ? "" : name + ".";
	}
/*
	function setAction(action : Trigger)
	{
		if (null != this.action)
			remove(this.action);
		_parentFor(action);
		this.action = action;
		return action;
	}
*/
	override function componentByPath(path : String) : INamedComponent
	{
		var components = [_component];
		if (null != action)
			components.push(action);
		for (component in components)
		{
			if (null == component)
				continue;
			var named = component.as(INamedComponent);
			if(null != named && named.path() == path)
				return named;
			var container = component.as(Container);
			if (null != container)
			{
				var c = container.componentByPath(path);
				if (null != c)
					return c;
			}
		}
		return null;
	}
	
	override function componentByName(name : String) : INamedComponent
	{
		var components = [_component];
		if (null != action)
			components.push(action);
		for (component in components)
		{
			if (null == component)
				continue;
			var named = component.as(INamedComponent);
			if(null != named && named.name == name)
				return named;
			var container = component.as(Container);
			if (null != container)
			{
				var c = container.componentByName(name);
				if (null != c)
					return c;
			}
		}
		return null;
	}
}